#include <iostream>
#include <memory>

// Abstract strateguy
class Strategy
{
public:
    virtual ~Strategy(){}
    virtual int execute(int a, int b) const = 0;
};

// Concrete Addition
class AddStrategy : public Strategy
{
public:
    int execute(int a, int b) const override
    {
        return a + b;
    }
};

// Concrete Substraction
class SubstractStrategy : public Strategy
{
public:
    int execute(int a, int b) const override
    {
        return a - b;
    }
};

// Concrete Multiplication
class MultiplyStrategy : public Strategy
{
public:
    int execute(int a, int b) const override
    {
        return a * b;
    }
};

// Concrete DivideStrategy
class DivideStrategy : public Strategy
{
public:
    int execute(int a, int b) const override
    {
        return a / b;
    }
};

// Context
class Calculator
{
public:
    Calculator(std::unique_ptr<Strategy> strategy) 
    : strategy_(std::move(strategy)){}

    int compute(int a, int b) const
    {
        return strategy_->execute(a, b);
    }

    void setStrategy(std::unique_ptr<Strategy> strategy)
    {
        strategy_ = std::move(strategy);
    }

private:
    std::unique_ptr<Strategy> strategy_;
};

int main()
{
    //Addition
    Calculator cal(std::make_unique<AddStrategy>());
    std::cout << "3 + 5 = " << cal.compute(3, 5) << std::endl;

    //Substraction
    cal.setStrategy(std::make_unique<SubstractStrategy>());
    std::cout << "3 - 5 = " << cal.compute(3, 5) << std::endl;

    //Multiplication
    cal.setStrategy(std::make_unique<MultiplyStrategy>());
    std::cout << "3 * 5 = " << cal.compute(3, 5) << std::endl;

    //DivideStrategy
    cal.setStrategy(std::make_unique<DivideStrategy>());
    std::cout << "3 / 5 = " << cal.compute(3, 5) << std::endl;    

    return 0;
}